package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumAttributeValueMapper;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.login.TsLogin;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.album.AlbumAttributeValue;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.query.album.AlbumInfoQuery;
import com.atguigu.tingshu.vo.album.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Select;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class AlbumInfoServiceImpl extends ServiceImpl<AlbumInfoMapper, AlbumInfo> implements AlbumInfoService {

	@Autowired
	private AlbumInfoMapper albumInfoMapper;
    @Autowired
	private AlbumAttributeValueMapper albumAttributeValueMapper;
	@Autowired
	private AlbumStatMapper albumStatMapper;
	@Autowired
	private RabbitService rabbitService;
	@Autowired
	private TrackStatMapper trackStatMapper;

	/**
	 * 跟踪更新音轨统计信息
	 * 根据提供的TrackStatMqVo对象更新音轨的统计信息，如果统计类型是播放，则同时更新相册的播放统计
	 *
	 * @param trackStatMqVo 包含音轨统计信息的VO对象，包括统计类型、音轨ID和计数
	 */
	@Override
	public void trackUpdateStat(TrackStatMqVo trackStatMqVo) {
	    // 更新音轨统计信息，根据统计类型、音轨ID和计数进行更新
	    trackStatMapper.updateTrackStat(trackStatMqVo.getStatType(), trackStatMqVo.getTrackId(), trackStatMqVo.getCount());

	    // 如果统计类型是播放统计
	    if (SystemConstant.TRACK_STAT_PLAY.equals(trackStatMqVo.getStatType())) {
	        // 更新相册的播放统计信息，使用相册ID、计数和相册统计类型
	        albumInfoMapper.updateAlbumStat(trackStatMqVo.getAlbumId(), trackStatMqVo.getCount(), SystemConstant.ALBUM_STAT_PLAY);
	    }
	}

	/**
	 * 根据专辑ID获取相册统计信息
	 *
	 * 此方法通过调用 albumStatMapper 的 selectAlbumStatVo 方法，
	 * 从数据库中查询指定专辑ID的统计信息
	 *
	 * @param albumId 专辑ID，用于标识特定的相册
	 * @return 返回包含专辑统计信息的 AlbumStatVo 对象
	 */
	@Override
	public AlbumStatVo getAlbumStatVo(Long albumId) {

	    return albumStatMapper.selectAlbumStatVo(albumId);
	}

	/**
	 * 根据专辑ID查询相册属性值列表
	 *
	 * @param albumId 专辑ID，用于定位特定专辑
	 * @return 返回专辑属性值列表，包含所有与指定专辑相关的属性值
	 */
	@Override
	public List<AlbumAttributeValue> findAlbumAttributeValue(Long albumId) {
	    // 使用LambdaQueryWrapper来构造查询条件，基于专辑ID查询专辑属性值
	    List<AlbumAttributeValue> albumAttributeValueList = albumAttributeValueMapper.selectList(
	        new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, albumId));

	    // 返回查询到的专辑属性值列表
	    return albumAttributeValueList;
	}

	/**
	 * 保存专辑信息，包括专辑属性值、统计信息等
	 * @param albumInfoVo
	 */
	@Transactional(rollbackFor = Exception.class)
	@Override
	public void saveAlbumInfo(AlbumInfoVo albumInfoVo) {
	    // 保存专辑信息到数据库
	    // 创建AlbumInfo对象并复制属性
	    AlbumInfo albumInfo = new AlbumInfo();
	    BeanUtils.copyProperties(albumInfoVo, albumInfo);
	    // 获取当前用户ID，如果为空则默认为1
	    Long userId = AuthContextHolder.getUserId() == null ? 1L : AuthContextHolder.getUserId();
	    albumInfo.setUserId(userId);

	    // 设置免费试听曲目数量，如果付费类型不是免费
	    if (!albumInfoVo.getPayType().equals(SystemConstant.ALBUM_PAY_TYPE_FREE)){
	        albumInfo.setTracksForFree(5);
	    }
	    // 设置专辑状态为通过
	    albumInfo.setStatus(SystemConstant.ALBUM_STATUS_PASS);
	    // 插入专辑信息到数据库
	    albumInfoMapper.insert(albumInfo);

	    // 保存专辑属性值到数据库
	    List<AlbumAttributeValueVo> albumAttributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList();
	    for (AlbumAttributeValueVo albumAttributeValueVo : albumAttributeValueVoList) {
	        AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
	        BeanUtils.copyProperties(albumAttributeValueVo, albumAttributeValue);
	        // 关联专辑ID
	        albumAttributeValue.setAlbumId(albumInfo.getId());
	        // 插入专辑属性值记录
	        albumAttributeValueMapper.insert(albumAttributeValue);
	    }

	    // 保存专辑统计信息到数据库
	    // 包括播放、订阅、浏览、评论等统计类型
	    this.saveAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_PLAY);
	    this.saveAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_SUBSCRIBE);
	    this.saveAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_BROWSE);
	    this.saveAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_COMMENT);
		if ("1".equals(albumInfoVo.getIsOpen())){
			rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM,MqConst.ROUTING_ALBUM_UPPER,albumInfo.getId());
		}
	}

	/**
	 * 保存专辑统计信息
	 *
	 * @param id 专辑ID
	 * @param albumStatPlay 统计类型，表示相册的播放统计
	 *
	 * 该方法创建一个新的AlbumStat对象，设置专辑ID和统计类型为相册的播放统计，
	 * 初始统计数量设置为0，然后将统计信息插入到数据库中。
	 */
	private void saveAlbumStat(Long id, String albumStatPlay) {
	    // 创建一个新的AlbumStat实例
	    AlbumStat albumStat = new AlbumStat();
	    // 设置专辑ID
	    albumStat.setAlbumId(id);
	    // 设置统计类型为专辑播放统计
	    albumStat.setStatType(albumStatPlay);
	    // 初始统计数量为0
	    albumStat.setStatNum(0);

	    // 将统计信息插入数据库
	    albumStatMapper.insert(albumStat);
	}
       /**
	 * 根据用户ID获取用户的所有专辑列表
	 *
	 * @param userId 用户ID，用于定位用户的专辑列表
	 * @return 返回用户的所有专辑列表，包含用户的所有专辑信息
	 */
	@Override
	public IPage<AlbumListVo> findUserAlbumPage(Page<AlbumListVo> page, AlbumInfoQuery albumInfoQuery) {
		return albumInfoMapper.selectAlbumInfoList(page, albumInfoQuery);
	}

	/**
	 * 删除专辑信息及其相关属性和统计信息
	 * 此方法不仅删除相册基本信息，还会删除与专辑相关的属性值和统计信息
	 * 确保彻底地清理数据库中与相册相关的所有数据
	 *
	 * @param albumId 专辑ID，用于定位数据库中的专辑记录
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void removeAlbumInfo(Long albumId) {
	    // 删除专辑基本信息
	    albumInfoMapper.deleteById(albumId);

	    // 删除专辑属性值
	    // 使用LambdaQueryWrapper进行条件查询，确保只删除与当前相册ID相关的属性值
	    albumAttributeValueMapper.delete(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, albumId));

	    // 删除专辑统计信息
	    // 同样使用LambdaQueryWrapper确保只删除与当前相册ID相关的统计信息
	    albumStatMapper.delete(new LambdaQueryWrapper<AlbumStat>().eq(AlbumStat::getAlbumId, albumId));
		rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM,MqConst.ROUTING_ALBUM_LOWER,albumId);
	}
   /**
	 * 根据专辑ID获取专辑信息
	 *
	 * @param albumId 专辑ID
	 * @return 相册详细信息对象
	 */
	@Override
	public AlbumInfo getAlbumInfo(Long albumId) {
		AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
		if (albumInfo!=null){
			List<AlbumAttributeValue> albumAttributeValueVoList = albumInfo.getAlbumAttributeValueVoList();

			List<AlbumAttributeValue> albumAttributeValueList = albumAttributeValueMapper.selectList(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, albumId));

             albumInfo.setAlbumAttributeValueVoList(albumAttributeValueList);

		}

		return albumInfo;
	}
   /**
	 * 更新专辑信息
	 *
	 * @param albumInfoVo 专辑信息VO对象，包含新的专辑信息
	 * @param albumId     专辑ID，用于定位要更新的专辑记录
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateAlbumInfo(AlbumInfoVo albumInfoVo, Long albumId) {
		// 更新albumInfo
		AlbumInfo albumInfo = new AlbumInfo();
		albumInfo.setId(albumId);
		BeanUtils.copyProperties(albumInfoVo, albumInfo);

		albumInfoMapper.updateById(albumInfo);

		// 更新albumAttributeValue
		// 先删除旧的属性值记录
		albumAttributeValueMapper.delete(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, albumId));

		// 复制新的属性值对象并插入数据库
		List<AlbumAttributeValueVo> albumAttributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList();
		if (!CollectionUtils.isEmpty(albumAttributeValueVoList)) {
			for (AlbumAttributeValueVo albumAttributeValueVo : albumAttributeValueVoList) {
				AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
				BeanUtils.copyProperties(albumAttributeValueVo, albumAttributeValue);

				albumAttributeValue.setAlbumId(albumId);
				albumAttributeValueMapper.insert(albumAttributeValue);
			}
		}

		// 根据专辑开放状态发送不同路由键的消息，以更新专辑展示状态
		if ("1".equals(albumInfoVo.getIsOpen())) {
			rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM, MqConst.ROUTING_ALBUM_UPPER, albumInfo.getId());
		} else {
			rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM, MqConst.ROUTING_ALBUM_LOWER, albumInfo.getId());
		}
	}


	/**
	 * 根据用户ID查询用户的所有相册列表
	 *
	 * @param userId 用户ID
	 * @return 包含相册信息的列表，每个专辑信息包括相册ID和相册标题
	 *
	 * 该方法通过限制查询字段和使用Lambda表达式来优化查询性能，同时限制返回结果数量为50

	 */

	@Override
	public List<AlbumInfo> findUserAllAlbumList(Long userId) {

		return albumInfoMapper.selectList(new LambdaQueryWrapper<AlbumInfo>()
				.eq(AlbumInfo::getUserId, userId)
				.select(AlbumInfo::getId, AlbumInfo::getAlbumTitle)
				.last("limit 50"));

	}
}
